<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    <title>canvas取点SVG描边实现的任意图片和文字的连线动画</title>
    <link rel="stylesheet" href="./canvas-getimgdata.css">
</head>
<body>
<div class="form">
    <div>
        <input type="radio" id="type1" name="type" value="file"><label for="type1">使用图片（含透明背景PNG或GIF）</label>
        <p><input type="file" id="file" accept="image/png,image/gif"></p>
    </div>
    <div>
        <input type="radio" id="type2" name="type" checked="" value="letter"><label for="type2">输入文字</label>
        <p><input maxlength="1" id="letter" size="4" autofocus></p>
    </div>
</div>
<svg id="plexus" width="320" height="320" viewbox="0 0 320 320"></svg>
<script>
(function() {
	/**!
	** @author: zhangxinxu(.com) 2017-12-09
	** @description: http://www.zhangxinxu.com/wordpress/?p=6594
	** @licence: MIT licence
	*/
	
    var el = document.getElementById("plexus");

    window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;

    var points = [];
    var gap = 13;

    // 计算像素点需要的canvas
    var canvas = document.createElement('canvas');
    // var canvas = document.querySelector('canvas');
    var context = canvas.getContext('2d');
    var width = 320;
    var height = 320;
    canvas.width = width;
    canvas.height = height;

    // get points方法
    var eleFile = document.getElementById('file');
    var eleLetter = document.getElementById('letter');

    // 图片尺寸限制在320*320里面
    // 压缩图片需要的一些元素和对象
    var reader = new FileReader(), img = new Image();

    // 选择的文件对象
    var file = null;

    // base64地址图片加载完毕后
    img.onload = function () {
        // 图片原始尺寸
        var originWidth = this.width;
        var originHeight = this.height;

        // 目标尺寸
        var targetWidth = originWidth, targetHeight = originHeight;

        // 按照canavs尺寸调整大小
        if (targetWidth > targetHeight)  {
            targetWidth = width;
            targetHeight = targetWidth * (originHeight / originWidth);
        } else {
            targetHeight = height;
            targetWidth = targetHeight * (originWidth / originHeight);
        }

        // 清除画布
        context.clearRect(0, 0, width, height);
        // 图片压缩
        context.drawImage(img, (width - targetWidth) / 2, (height - targetHeight) / 2, targetWidth, targetHeight);
        // 获得像素点坐标
        getPoints();
        // 动画
        refreshPoints();
    };

    // 文件base64化，以便获知图片原始尺寸
    reader.onload = function(e) {
        img.src = e.target.result;
    };
    // 选择文件
    eleFile.addEventListener('change', function (event) {
        file = event.target.files[0];
        // 选择的文件是图片
        if (file.type.indexOf("image") == 0) {
            reader.readAsDataURL(file);
        }
    });

    // 如果是输入文字
    eleLetter.addEventListener('change', function () {
        if (this.value && this.value.length == 1) {
            context.fillStyle = 'white';
            context.textBaseline = 'middle';
            context.textAlign = 'center';
            context.font = 'bold 280px arial';
            // 清除画布
            context.clearRect(0, 0, width, height);
            // 绘制文本
            context.fillText(this.value, width/2, height/2);
            // 获得像素点坐标
            getPoints();
            // 动画
            refreshPoints();
        }
    });
	
    var getPoints = function () {
        var imgData = context.getImageData(0,0,width,height).data;

        var pos = [];
        var x = 0, y = 0, index = 0;
        for (var i=0; i<imgData.length; i+=(4*gap)) {
            if (imgData[i+3] == 255) {
                // 塞入此时的坐标
                pos.push({
                    x: x,
                    y: y
                });
            }
            index = Math.floor(i / 4);
            x = index % width;
            y = Math.floor(index / width);
            if (x >= width - gap) {
                i += gap * 4 * width;
            }
        }

        points = pos;
    };
	
    var maxDistance = 31, minDistance = 0;

    var getDistance = function(point1, point2) {
        return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));
    }

    var refreshPoints = function() {
        el.innerHTML = '';

        var lines = [];
        for (var i = points.length - 1; i >= 0; i--) {
            for (var j = 0, _length = points.length; j < _length; j++) {
                var distance = getDistance(points[j], points[i]);
                if ((points[i].x == points[j].x && points[i].y == points[j].y) || distance > maxDistance || distance < minDistance)
                    continue;
                var line = document.createElementNS('http://www.w3.org/2000/svg', "line")
                line.setAttribute('x1', points[i].x);
                line.setAttribute('y1', points[i].y);
                line.setAttribute('x2', points[j].x);
                line.setAttribute('y2', points[j].y);
                line.setAttribute("class", "plexus-line")
                line.style.strokeDasharray = distance + " " + distance;
                line.style.strokeDashoffset = distance;
                line.style.transitionDelay = line.style.WebkitTransitionDelay = ((i * 50 % 1500) / 1000) + "s"
                el.appendChild(line);
                lines.push(line);
            };
        };

        // console.log(lines.length);

        window.requestAnimationFrame(function() {
            for (var i = lines.length - 1; i >= 0; i--) {
                lines[i].style.strokeDashoffset = 0;
                lines[i].style.transitionDelay = 2 * Math.random() + 's';
            };
        })
    }
})();
</script>
<!-- 
<style>.iknow {position: absolute; bottom: 10px; left: 0; right:0; width: 728px; margin: auto; }</style>
<div class="iknow">
    <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
    <ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-0090627341039040" data-ad-slot="4686885989"></ins>
</div> -->
<!-- <script>
// 移动端不显示该广告
if (screen.width < 640) {
	var eleIkonw = document.querySelector('.iknow');
	if (eleIkonw) {
		eleIkonw.parentNode.removeChild(eleIkonw);	
	}
} else {
	(adsbygoogle = window.adsbygoogle || []).push({});
}
</script> -->
<!-- <script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-11205167-1']);
  _gaq.push(['_trackPageview']);
  (function() {
	var ga = document.createElement('script');
	ga.type = 'text/javascript';
	ga.async = true;
	ga.src = 'http://www.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(ga, s);
  })();
</script> -->
</body>
</html>